<!DOCTYPE html>
<html>
	<head>
		<base href="$$literal-vsuri$$/index.html" />
		<script type="text/javascript">
			var log;
			var editorUi;
			(() => {
				const api = (window.VsCodeApi = acquireVsCodeApi());
				function sendToVsCode(msg) {
					api.postMessage(JSON.stringify(msg));
				}
				log = function log(...msg) {
					sendToVsCode({ event: "log", body: msg });
				};

				Object.defineProperty(window, "mxIsElectron", {
					value: false,
				});

				// Fix draw.io tries to access unavailable localStorage
				// Replace it with a bridged version
				const storage = $$localStorage$$;
				const bridgedLocalStorage = {
					getItem: function (key) {
						log("localStorage: get " + key);
						return storage[key];
					},
					setItem: function (key, val) {
						log("localStorage: set " + key + " to " + val);
						storage[key] = val;
						sendToVsCode({
							event: "updateLocalStorage",
							newLocalStorage: storage,
						});
					},
					removeItem: function (key) {
						log("localStorage: remove " + key);
						delete storage[key];
					},
				};
				Object.defineProperty(window, "localStorage", {
					value: bridgedLocalStorage,
				});

				// Fix draw.io tries to access unavailable cookie prop
				Object.defineProperty(document, "cookie", { value: "" });

				// See EditorUI.js:10675
				const fakedWindowOpener = {
					postMessage: (msg) => api.postMessage(msg),
				};
				Object.defineProperty(window, "opener", {
					value: fakedWindowOpener,
				});

				window.addEventListener("message", function (evt) {
					if (evt.source !== fakedWindowOpener) {
						let evtData = evt.data;
						if (evtData) {
							try {
								var dataObj = JSON.parse(evtData);
							} catch (e) {}
						}

						if (dataObj) {
							if (
								dataObj.action === "export" &&
								editorUi.fileNode
							) {
								// fix default export settings

								var scale = Number.parseFloat(
									editorUi.fileNode.getAttribute("scale")
								);
								if (!Number.isNaN(scale)) {
									dataObj.scale = scale;
								}

								var border = Number.parseFloat(
									editorUi.fileNode.getAttribute("border")
								);
								if (!Number.isNaN(border)) {
									dataObj.border = border;
								}
							}
							evtData = JSON.stringify(dataObj);
						}

						// Re-emit messages with faked source, so that drawio handles the payload.
						// If we don't do this, `evt.source === window.opener` will fail
						// and drawio ignores the message.
						const fakedEvt = new Event("message");
						fakedEvt.source = fakedWindowOpener;
						fakedEvt.data = evtData;

						// When loading a document, dispatchEvent would indirectly call window.focus.
						// This is not recommended behavior in VS Code, so we disable it.
						const origFocus = window.focus;
						window.focus = function () {
							/* NOOP */
						};

						try {
							window.dispatchEvent(fakedEvt);
						} finally {
							window.focus = origFocus;
						}

						evt.stopPropagation();
						evt.preventDefault();
					}
				});
			})();

			var appearance = parseInt($$appearance$$),
				theme = $$theme$$;

			var urlParams = {
				embed: "1",
				configure: "1",
				proto: "json",
				ui: theme,
				dark: theme === "dark" || appearance & 1 ? "1" : "0",
				"high-contrast": appearance & 2 ? "1" : "0",
				lang: $$lang$$,
				noSaveBtn: "1",
				noExitBtn: "1",
				chrome: $$chrome$$,
				get ["svg-warning"]() {
					return editorUi.fileNode.getAttribute(
						"disableSvgWarning"
					) === "true"
						? "0"
						: "1";
				},
			};

			// Checks for local storage
			var isLocalStorage = true;

			function mxscript(src, onLoad, id, dataAppKey, noWrite) {
				if (onLoad != null || noWrite) {
					var s = document.createElement("script");
					s.setAttribute("type", "text/javascript");
					s.setAttribute("src", src);
					var r = false;

					if (id != null) {
						s.setAttribute("id", id);
					}

					if (dataAppKey != null) {
						s.setAttribute("data-app-key", dataAppKey);
					}

					if (onLoad != null) {
						s.onload = s.onreadystatechange = function () {
							if (
								!r &&
								(!this.readyState ||
									this.readyState == "complete")
							) {
								r = true;
								onLoad();
							}
						};
					}

					var t = document.getElementsByTagName("script")[0];

					if (t != null) {
						t.parentNode.insertBefore(s, t);
					}
				} else {
					document.write(
						'<script src="' +
							src +
							'"' +
							(id != null ? ' id="' + id + '" ' : "") +
							(dataAppKey != null
								? ' data-app-key="' + dataAppKey + '" '
								: "") +
							"></scr" +
							"ipt>"
					);
				}
			}

			function mxinclude(src) {
				var g = document.createElement("script");
				g.type = "text/javascript";
				g.async = true;
				g.src = src;

				var s = document.getElementsByTagName("script")[0];
				s.parentNode.insertBefore(g, s);
			}
		</script>
		<meta
			name="viewport"
			content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"
		/>
		<link rel="stylesheet" type="text/css" href="styles/grapheditor.css" />
		<link
			rel="stylesheet"
			media="(forced-colors: active)"
			href="styles/high-contrast.css"
			id="high-contrast-stylesheet"
		/>
		<link rel="manifest" href="images/manifest.json" />
		<style type="text/css">
			body {
				overflow: hidden;
				padding: 0;
			}

			div.picker {
				z-index: 10007;
			}

			.geSidebarContainer .geTitle input {
				font-size: 8pt;
				color: #606060;
			}

			.geBlock {
				z-index: -3;
				margin: 100px;
				margin-top: 40px;
				margin-bottom: 30px;
				padding: 20px;
				text-align: center;
				min-width: 50%;
			}

			.geBlock h1,
			.geBlock h2 {
				margin-top: 0px;
				padding-top: 0px;
			}

			.geEditor * {
				color: light-dark(var(--text-color), var(--dark-text-color));
				scrollbar-color: light-dark(#e2e2e2, #4b4b4b)
					light-dark(#fbfbfb, var(--dark-panel-color));
			}

			.geEditor *:not(.geScrollable)::-webkit-scrollbar {
				width: 10px;
				height: 10px;
			}

			.geEditor ::-webkit-scrollbar-track {
				background-clip: padding-box;
				border: solid transparent;
				border-width: 1px;
			}

			.geEditor ::-webkit-scrollbar-corner {
				background-color: transparent;
			}

			.geEditor ::-webkit-scrollbar-thumb {
				background-color: rgba(0, 0, 0, 0.1);
				background-clip: padding-box;
				border: solid transparent;
				border-radius: 10px;
			}

			.geEditor ::-webkit-scrollbar-thumb:hover {
				background-color: rgba(0, 0, 0, 0.4);
			}

			.geTemplate {
				border: 1px solid transparent;
				display: inline-block;
				_display: inline;
				vertical-align: top;
				border-radius: 3px;
				overflow: hidden;
				font-size: 14pt;
				cursor: pointer;
				margin: 5px;
			}
		</style>
		<script src="js/PreConfig.js"></script>
		<script src="js/app.min.js"></script>
		<script src="js/extensions.min.js"></script>
		<script src="js/stencils.min.js"></script>
		<script src="js/shapes-14-6-5.min.js"></script>
		<script src="js/PostConfig.js"></script>
	</head>

	<body class="geEditor">
		<div id="geInfo">
			<div class="geBlock" style="text-align: center; min-width: 50%">
				<h1>Flowchart Maker and Online Diagram Software</h1>
				<p>
					diagrams.net (formerly draw.io) is free online diagram
					software. You can use it as a flowchart maker, network
					diagram software, to create UML online, as an ER diagram
					tool, to design database schema, to build BPMN online, as a
					circuit diagram maker, and more. draw.io can import .vsdx,
					Gliffy&trade; and Lucidchart&trade; files .
				</p>
				<h2 id="geStatus">Loading...</h2>
			</div>
		</div>
		<script type="text/javascript">
			(() => {
				function patchFn(clazz, fnName, fnFactory) {
					var old = clazz[fnName];
					clazz[fnName] = fnFactory(old);
				}

				log("Document loaded, patching prototypes");

				patchFn(Menus.prototype, "addSubmenu", function (old) {
					return function (...args) {
						if (
							args[0] === "exportAs" ||
							args[0] === "importFrom"
						) {
							return;
						}
						//console.log("addSubmenu: ", args[0]);
						return old.apply(this, args);
					};
				});

				patchFn(Menus.prototype, "addMenuItem", function (old) {
					return function (...args) {
						if (
							[
								"print",
								"saveAndExit",
								"plugins",
								"exit",
								//"properties",
							].indexOf(args[1]) !== -1
						) {
							return;
						}
						//console.log("addMenuItem: ", args[1]);
						return old.apply(this, args);
					};
				});

				// Without this, it will crash. "help" is removed.
				Menus.prototype.defaultMenuItems =
					Menus.prototype.defaultMenuItems.filter(
						(i) => i !== "help"
					);

				patchFn(Menus.prototype, "put", function (old) {
					return function (...args) {
						if (["language", "help"].indexOf(args[0]) !== -1) {
							return args[1];
						}
						//console.log("put: ", args[0]);
						return old.apply(this, args);
					};
				});

				EditorUi.prototype.addEmbedButtons = () => {};

				patchFn(EditorUi.prototype, "init", function (old) {
					return function (...args) {
						editorUi = this;
						const result = old.apply(this, args);
						return result;
					};
				});

				// This prevents Draw.io from overriding VS Code commands
				patchFn(mxEvent, "addListener", function (old) {
					return function (...args) {
						const [target, eventName, oldHandler] = args;
						// console.log("Intercepting addListener", args);
						if (eventName === "keydown") {
							args[2] = (/** @type {KeyboardEvent} */ keyEvt) => {
								//console.log("Handling key", keyEvt);
								//log("Handling key", keyEvt.key);

								// Draw.io should not override these shortcuts
								if (keyEvt.key === "Tab" && keyEvt.ctrlKey) {
									return;
								}
								if (
									keyEvt.key === "P" &&
									(keyEvt.ctrlKey || keyEvt.metaKey)
								) {
									// this covers ctrl+shift+p.
									return;
								}
								if (
									keyEvt.key === "p" &&
									(keyEvt.ctrlKey || keyEvt.metaKey)
								) {
									// this covers ctrl+p.
									// We don't need this keyboard shortcuts in drawio.
									// Printing does not make sense in VS Code.
									// Users should use the drawio desktop app for that.
									return;
								}
								if (
									keyEvt.key === "S" &&
									keyEvt.shiftKey &&
									keyEvt.altKey
								) {
									// See https://github.com/hediet/vscode-drawio/issues/144
									// This shortcut destroys the diagram.
									return;
								}
								if (
									keyEvt.key === "S" &&
									keyEvt.ctrlKey &&
									keyEvt.shiftKey
								) {
									// We are handling saving ourselves. This action does not make sense.
									return;
								}

								oldHandler(keyEvt);
							};
						}

						return old.apply(this, args);
					};
				});

				/**
				 * See https://github.com/jgraph/mxgraph/blob/master/javascript/src/js/util/mxUrlConverter.js
				 * for non minified version.
				 * Fixes https://github.com/hediet/vscode-drawio/issues/53 and
				 * https://github.com/hediet/vscode-drawio/issues/74.
				 */
				function fix_mxUrlConverter_prototype_convert() {
					mxUrlConverter.prototype.baseUrl = "$$literal-vsuri$$/";
					mxUrlConverter.prototype.updateBaseUrl = function () {
						this.baseDomain = "$$literal-vsuri$$";
						this.baseUrl = "$$literal-vsuri$$/";
					};
					const RX_IS_ABS_URL = /^(\/\/|[a-zA-Z][a-zA-Z\d+\-.]*:)/;
					mxUrlConverter.prototype.isRelativeUrl = function (url) {
						return url != null && !RX_IS_ABS_URL.test(url);
					};
				}

				fix_mxUrlConverter_prototype_convert();

				// Fix linkTarget export
				// This is super hacky.
				// See https://github.com/hediet/vscode-drawio/issues/204.
				patchFn(Graph.prototype, "getSvg", function (old) {
					return function (
						background,
						scale,
						border,
						nocrop,
						crisp,
						ignoreSelection,
						showText,
						imgExport,
						linkTarget,
						hasShadow,
						incExtFonts,
						keepTheme,
						exportType,
						...args
					) {
						const baseLinkTarget =
							editorUi.fileNode.getAttribute("linkTarget");
						linkTarget = linkTarget || baseLinkTarget;

						return old.apply(this, [
							background,
							scale,
							border,
							nocrop,
							crisp,
							ignoreSelection,
							showText,
							imgExport,
							linkTarget,
							hasShadow,
							incExtFonts,
							keepTheme,
							exportType,
							...args,
						]);
					};
				});

				// Force compact to exclude noisy properties
				patchFn(EditorUi.prototype, "createFileData", function (old) {
					return function (
						node,
						graph,
						file,
						url,
						forceXml,
						forceSvg,
						forceHtml,
						embeddedCallback,
						ignoreSelection,
						compact,
						uncompressed
					) {
						return old.apply(this, [
							node,
							graph,
							file,
							url,
							forceXml,
							forceSvg,
							forceHtml,
							embeddedCallback,
							ignoreSelection,
							/* compact */ true,
							uncompressed,
						]);
					};
				});

				patchFn(mxUtils, "getXml", function (old) {
					return function (node) {
						// https://github.com/hediet/vscode-drawio/issues/209
						const xmlSerializer = new XMLSerializer();
						xml = xmlSerializer.serializeToString(node);
						return xml;
					};
				});

				App.main();

				// For debugging:
				// console.log("drawio", window.Draw);

				/**
				 * @param url {string}
				 */
				function loadScript(url) {
					console.log("load custom plugin:", url);
					const pluginScript = document.createElement("script");
					pluginScript.type = "text/javascript";
					pluginScript.src = url;
					document
						.getElementsByTagName("head")[0]
						.appendChild(pluginScript);
				}
				/**
				 * @param url {string[]}
				 */
				function loadScripts(urls) {
					urls.forEach(loadScript);
				}
				loadScripts($$customPluginPaths$$);

				/**
				 * @param src {string}
				 */
				function loadScriptSrc(src) {
					const pluginScript = document.createElement("script");
					pluginScript.type = "text/javascript";
					pluginScript.text = src;

					document
						.getElementsByTagName("head")[0]
						.appendChild(pluginScript);
				}

				$$additionalCode$$.forEach(loadScriptSrc);
			})();
		</script>
	</body>
</html>
